/*
 * IncomeStatement.cpp
 *
 *  Created on: Mar 26, 2014
 *      Author: alexander
 */

#include "FinancialData.h"

#include <string>

#include "Poco/StringTokenizer.h"
//#include "Poco/String.h"

//	for (int i = 0; i < SIZE; i++)
//	{
//		if (flags[i] == 0)
//		{
//			std::cout << "[!!!] \"" << CATEGORIES[i] << "\" not found" << std::endl;
//			throw std::exception();
//		}
//	}

/*********** Income Statement *************/
//const std::vector<std::string> IncomeStatement::CATEGORIES =
//{
//		"Total Revenue",
//		"Cost of Revenue",
//		"Gross Profit",
//		"Research and Development",
//		"Sales, General and Admin.",
//		"Non-Recurring Items",
//		"Other Operating Items",
//		"Operating Income",
//		"Add'l income/expense items",
//		"Earnings Before Tax",
//		"Income Tax",
//		"Minority Interest",
//		"Equity Earnings/Loss Unconsolidated Subsidiary",
//		"Net Income-Cont. Operations",
//		"Net Income",
//		"Net Income Applicable to Common Shareholders"
//};

const std::vector<std::string> IncomeStatement::CATEGORIES =
{
		"Revenue",
		"Other Revenue, Total",
		"Total Revenue",
		"Cost of Revenue, Total",
		"Gross Profit",
		"Selling/General/Admin. Expenses, Total",
		"Research &amp; Development",
		"Depreciation/Amortization",
		"Interest Expense(Income) - Net Operating",
		"Unusual Expense (Income)",
		"Other Operating Expenses, Total",
		"Total Operating Expense",
		"Operating Income",
		"Interest Income(Expense), Net Non-Operating",
		"Gain (Loss) on Sale of Assets",
		"Other, Net",
		"Income Before Tax",
		"Income After Tax",
		"Minority Interest",
		"Equity In Affiliates",
		"Net Income Before Extra. Items",
		"Accounting Change",
		"Discontinued Operations",
		"Extraordinary Item",
		"Net Income",
		"Preferred Dividends",
		"Income Available to Common Excl. Extra Items",
		"Income Available to Common Incl. Extra Items",
		"Gross Dividends - Common Stock",
		"Net Income after Stock Based Comp. Expense",
		"Depreciation, Supplemental",
		"Total Special Items",
		"Normalized Income Before Taxes",
		"Effect of Special Items on Income Taxes",
		"Income Taxes Ex. Impact of Special Items",
		"Normalized Income After Taxes",
		"Normalized Income Avail to Common",
};

const std::vector<std::string> IncomeStatement::CATEGORIES_PER_SHARE =
{
		"Basic Weighted Average Shares",
		"Basic EPS Excluding Extraordinary Items",
		"Basic EPS Including Extraordinary Items",
		"Dilution Adjustment",
		"Diluted Weighted Average Shares",
		"Diluted EPS Excluding Extraordinary Items",
		"Diluted EPS Including Extraordinary Items",
		"Dividends per Share - Common Stock Primary Issue",
		"Basic EPS after Stock Based Comp. Expense",
		"Diluted EPS after Stock Based Comp. Expense",
		"Basic Normalized EPS",
		"Diluted Normalized EPS",
};

/*********** Balance Sheet *************/
const std::vector<std::string> BalanceSheet::CATEGORIES =
{
		// Current Assets
		"Cash &amp; Equivalents",
		"Short Term Investments",
		"Cash and Short Term Investments",
		"Accounts Receivable - Trade, Net",
		"Receivables - Other",
		"Total Receivables, Net",
		"Total Inventory",
		"Prepaid Expenses",
		"Other Current Assets, Total",
		"Total Current Assets",

		// Long-Term Assets
		"Property/Plant/Equipment, Total - Gross",
		"Accumulated Depreciation, Total",
		"Goodwill, Net",
		"Intangibles, Net",
		"Long Term Investments",
		"Other Long Term Assets, Total",

		"Total Assets",

		// Current Liabilities
		"Accounts Payable",
		"Accrued Expenses",
		"Notes Payable/Short Term Debt",
		"Current Port. of LT Debt/Capital Leases",
		"Other Current liabilities, Total",
		"Total Current Liabilities",

		// Long Term Debt
		"Long Term Debt",
		"Capital Lease Obligations",
		"Total Long Term Debt",

		// Total Liabilities
		"Total Debt",
		"Deferred Income Tax",
		"Minority Interest",
		"Other Liabilities, Total",
		"Total Liabilities",

		// Stock Holders Equity
		"Redeemable Preferred Stock, Total",
		"Preferred Stock - Non Redeemable, Net",
		"Common Stocks, Total",
		"Additional Paid-In Capital",
		"Retained Earnings (Accumulated Deficit)",
		"Treasury Stock - Common",
		"Other Equity, Total",
		"Total Equity",

		"Total Liabilities &amp; Shareholders&#39; Equity",
		"Shares Outs - Common Stock Primary Issue",
		"Total Common Shares Outstanding",
};

/*********** Cash Flow *************/
const std::vector<std::string> CashFlow::CATEGORIES =
{
		"Net Income/Starting Line",

		// Cash Flows-Operating Activities
		"Depreciation/Depletion",
		"Amortization",
		"Deferred Taxes",
		"Non-Cash Items",
		"Changes in Working Capital",
		"Cash from Operating Activities",

		// Cash Flows-Investing Activities
		"Capital Expenditures",
		"Other Investing Cash Flow Items, Total",
		"Cash from Investing Activities",

		// Cash Flows-Financing Activities
		"Financing Cash Flow Items",
		"Total Cash Dividends Paid",
		"Issuance (Retirement) of Stock, Net",
		"Issuance (Retirement) of Debt, Net",
		"Cash from Financing Activities",

		"Foreign Exchange Effects",
		"Net Change in Cash",
		"Cash Interest Paid, Supplemental",
		"Cash Taxes Paid, Supplemental",
};

/*********** Financial Ratios *************/
const std::vector<std::string> FinancialRatios::CATEGORIES =
{
		// Liquidity Ratios
		"Current Ratio",
		"Quick Ratio",
		"Cash Ratio",

		// Profitability Ratios
		"Gross Margin",
		"Operating Margin",
		"Pre-Tax Margin",
		"Profit Margin",
		"Pre-Tax ROE",
		"After Tax ROE",
};

/*********** Key Statistics *************/
const std::vector<std::string> KeyStatistics::CATEGORIES =
{
		// Valuation Measures
		"Market Cap (intraday)",
		"Enterprise Value",
		"Trailing P/E (ttm, intraday)",
		"Price/Sales (ttm)",
		"Price/Book (mrq)",
		"Enterprise Value/Revenue (ttm)",
		"Enterprise Value/EBITDA (ttm)",

		// Financial Highlights
		// Profitability
		"Profit Margin (ttm)",
		"Operating Margin (ttm)",
		// Management Effectiveness
		"Return on Assets (ttm)",
		"Return on Equity (ttm)",
		// Income Statement
		"Revenue per Share (ttm)",
		"Qtrly Earnings Growth (yoy)",
		"Diluted EPS (ttm)",
		"Qtrly Earnings Growth (yoy)",
		// Balance Sheet
		"Total Cash Per Share (mrq)",
		"Total Debt/Equity (mrq)",
		"Current Ratio (mrq)",
		"Book Value Per Share (mrq)",
		// Cash Flow Statement
		"Operating Cash Flow (ttm)",
		"Levered Free Cash Flow (ttm)",

		// Share Statistics
		"Avg Vol",
		"Shares Outstanding",

		// Dividends & Splits
		"Trailing Annual Dividend Yield",
		"5 Year Average Dividend Yield",
		"Payout Ratio",
		//"Dividend Date",
};

std::map<std::string, float>& KeyStatistics::parseWebPageAndSet(const std::vector<std::string>& webPageSource)
{
	std::vector<std::string> years;
	const int SIZE = CATEGORIES.size();
	std::vector<unsigned char> flags(SIZE, 0);

	//int j = 0;

	for (auto it = webPageSource.begin(),
			end_it = webPageSource.end(); it != end_it; ++it) //, j++)
	{
		for (int j = 0; j < SIZE; j++)
		{
			if (flags[j])
			{
				continue;
			}
			std::size_t pos = Poco::isubstr<std::string>(*it, CATEGORIES[j]);
			if (pos != std::string::npos)
			{
				Poco::RegularExpression re("[0-9][0-9]*[\.][0-9]+[KMB%]?");
				std::string valueStr;
				if (re.extract(*it, pos, valueStr) > 0)
				{
					float multiplier = 1;
					if (valueStr.find("K") != std::string::npos)
					{
						multiplier *= 1000;
						Poco::translateInPlace(valueStr, "K", "");
					}
					else if (valueStr.find("M") != std::string::npos)
					{
						multiplier *= 1000000;
						Poco::translateInPlace(valueStr, "M", "");
					}
					else if (valueStr.find("B") != std::string::npos)
					{
						multiplier *= 1000000000;
						Poco::translateInPlace(valueStr, "B", "");
					}
					else if (valueStr.find("%") != std::string::npos)
					{
						multiplier *= 0.01;
						Poco::translateInPlace(valueStr, "%", "");
					}
					float n = Poco::NumberParser::parseFloat(valueStr);
//					std::cout << CATEGORIES[j] << ": " << multiplier * n << std::endl;
					values[CATEGORIES[j]] = multiplier * n;
					flags[j] = 1;
				}
			}
		}
	}

	for (int i = 0; i < SIZE; i++)
	{
		if (flags[i] == 0)
		{
			std::cout << "[!!!] Key Statistics: \"" << CATEGORIES[i] << "\" not found" << std::endl;
			throw std::exception();
		}
	}

	return values;
}
